package com.example.demo.data;

import com.example.demo.service.CoreService;
import com.example.demo.service.DataQueryService;
import com.example.demo.service.PackService;
import com.example.demo.vo.Boutlist;
import com.example.demo.vo.Boutlistdetail;
import com.example.demo.vo.Pallroutecomb;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by ltian on 2020/1/16.
 */
@Slf4j
@Component
public class Dao {

//    @Autowired
//    @Qualifier("primaryJdbcTemplate")
//    protected JdbcTemplate jdbcTemplate2;

    @Autowired
    @Qualifier("secondaryJdbcTemplate")
    protected JdbcTemplate jdbcTemplate;

    @Autowired
    private SxConfig config;

    @Autowired
    private DataQueryService dataQueryService;

    @Autowired
    private CoreService coreService;

    @Autowired
    private PackService packService;

    @Autowired
    private TradeDao tradeDao;

    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static final int BATCH_SIZE = 100;

    @PostConstruct
    public void doTask() {
        LocalDate date1 = parseDateString(config.getDate1());
        LocalDate date2 = parseDateString(config.getDate2());
        if (date1 == null || date2 == null) {
            System.err.println("error: can not parse date from config file");
            return;
        }

        while (!date1.isAfter(date2)) {
            log.info("task for : {}", formatter.format(date1));
            final int squaddate = Integer.valueOf(formatter.format(date1));
            new Thread(() -> {
                if (config.getJob() == 0) {
                    doTask(squaddate);
                    int affected = coreService.updateOtherVehicle(squaddate);
                    log.warn("update OtherVehicle:{}, affected: {}", squaddate, affected);
                } else {
                    tradeDao.doTask(squaddate);
                }

                packService.afterBatchHandle(squaddate);
            }).start();

            date1 = date1.plusDays(1);
        }

    }

    private boolean isETC() {
        return config.getBoutlist().toUpperCase().startsWith("ETC");
    }


    private void doTask(int squaddate) {
        int scanCount = 0;
        String offsetNo = "0";
        while (true) {

            List<Boutlist> boutListRows = queryBoutList(squaddate, offsetNo, BATCH_SIZE);
            scanCount += boutListRows.size();
            log.info("scan boutlist, squaddate: {}, count: {}", squaddate, scanCount);
            if (boutListRows.isEmpty()) {
                log.info("done, squaddate:{}", squaddate);
                break;
            }
            offsetNo = boutListRows.get(boutListRows.size() - 1).getListno();

            for (Boutlist bout : boutListRows) {
                try {
                    if (bout.getListno().length() != 37) {
                        log.warn("listno.length != 37， {}", bout.getListno());
                        coreService.abort(bout);
                        continue;
                    }


                    // ETC收费时间小于2020, 将其修改为收到数据的时间
                    if (isETC() && bout.getOptime() != null && bout.getOptime().toLocalDate().getYear() < 2020) {
                        java.sql.Date opTime = parseOpTime(bout.getListno());
                        if (opTime == null) {
                            coreService.abort(bout);
                            continue;
                        }
                        bout.setOptime(opTime);
                    }

                    if (bout.getCardno() == null || bout.getElecardno() == null || bout.getElecardid() == null || bout.getElecardtype() == null || bout.getElecardtype() == 0 && isETC()) {
                        log.warn("ETC, bad eleCardType or cardNo， {}", bout.getListno());
                        coreService.abort(bout);
                        continue;
                    }


                    String vehplate = bout.getVehplate();    // 出口车牌
                    String invehplate = bout.getInvehplate();//入口车牌
                    String vehplateAuto = bout.getVehplateauto();//识别车牌
                    if (!coreService.isValidatePlate(vehplate)) {
                        if (!coreService.isValidatePlate(invehplate)) {
                            log.warn("invalid vahicle plate, in:{}, out:{}, listno:{}", invehplate, vehplate, bout.getListno());
                            coreService.abort(bout);
                            continue;
                        } else {
                            vehplate = invehplate;
                        }
                    } else if (!coreService.isValidatePlate(invehplate)) {
                        invehplate = vehplate;
                    }

                    if (!coreService.isValidatePlate(vehplateAuto) || vehplateAuto.equals("*****")) {
                        vehplateAuto = vehplate;
                    }

                    String exTolllandid = bout.getExtolllaneid();
                    if (bout.getExtolllaneid() == null || bout.getExtolllaneid().length() < 14) {
                        exTolllandid = dataQueryService.queryExLandIdByStationNo(bout.getStationno());

                        if (exTolllandid == null || exTolllandid.length() < 14) {
                            log.warn("bout has  invalid extolllaneid, listno: {}, landId：{}", bout.getListno(), bout.getExtolllaneid());
                            coreService.abort(bout);
                            continue;
                        }
                    }


//                    List<Boutlistdetail> oldDetails = queryBoutDetailList(bout.getListno());

//                    List<Boutlistdetail> oldDetails = new ArrayList<>();//不查明细，后续直接删除旧的明细

//                    log.debug("old details: {}", oldDetails);
                    // 已有明细存在且金额相同的跳过处理
//                    long total = oldDetails.stream().mapToLong(Boutlistdetail::getTollfee).sum();
//                    if (total == bout.getTotaltoll()) {
//                        continue;
//                    }
                    String entolllaneid = bout.getEntolllaneid();
                    String entolllanehex = bout.getEntolllanehex();
                    String passId = bout.getPassid();
                    String cardNo = bout.getCardno();
                    // cardNo, passId
                    Pair<String, String> cardPair = fixCardnoAndPassId(cardNo, bout.getCardid(), passId);
                    cardNo = cardPair.getLeft();
                    passId = cardPair.getRight();
                    if (passId == null || passId.length() == 0) {
                        coreService.abort(bout);
                        log.warn("blank passid:{}", bout.getListno());
                        continue;
                    }

                    if (bout.getEntolllaneid() == null || bout.getEntolllaneid().length() < 21) {
                        if (bout.getEntolllanehex() == null) {
                            log.warn("blank entolllanehex, lineno:{}, entolllanehex:{}", bout.getListno(), bout.getEntolllanehex());
                            coreService.abort(bout);
                            continue;
                        }

//                        entolllaneid = queryEnLandId(bout.getEntolllanehex());
//
//                        if (entolllaneid == null || entolllaneid.length() < 21) {
//                            log.debug("found invalid id from basicInfoHex, listno: {}, Entolllanehex: {}", bout.getListno(), bout.getEntolllanehex());
//                            continue;
//                        }

                        if (bout.getEntolllanehex().length() == 10) {
                            // 取车道号
                            entolllaneid = dataQueryService.queryLaneId(bout.getEntolllanehex());
                            if (entolllaneid == null || entolllaneid.length() < 21) {
                                String stationId = dataQueryService.queryStationId(bout.getEntolllanehex().substring(0, 8));
                                if (stationId == null || stationId.length() != 14) {
                                    log.warn("====>  found invalid stationId from basicInfoHex, listno: {}, Entolllanehex: {}", bout.getListno(), bout.getEntolllanehex());
                                    coreService.abort(bout);
                                    continue;
                                }
                                entolllaneid = stationId + "2020010";
                            }


                        } else if (bout.getEntolllanehex().length() == 8) {
                            // 根据车站号取最后一个车道号和10位的hex
                            Pair<String, String> pair = dataQueryService.queryLandIdAndHex(bout.getEntolllanehex());
                            if (pair == null) {
                                log.warn("can not find basicinfo from hex8, listno:{}", bout.getListno());
                                coreService.abort(bout);
                                continue;
                            }

                            entolllaneid = pair.getLeft();
                            entolllanehex = pair.getRight(); //10位的hex
                            if (entolllaneid == null || entolllaneid.length() < 21) {
                                entolllaneid = dataQueryService.queryEnLandId(1, bout.getEntolllanehex().substring(0, 8));//stationId
                                if (entolllaneid == null || entolllaneid.length() != 14) {
                                    log.warn("====>  found invalid id from basicInfoHex, listno: {}, Entolllanehex: {}", bout.getListno(), bout.getEntolllanehex());
                                    coreService.abort(bout);
                                    continue;
                                }
                                entolllaneid = entolllaneid + "2020010";
                            }

                        } else {
                            log.warn("bad Entolllanehex, len not in [8,10] listno:{}, hex:{}", bout.getListno(), bout.getEntolllanehex());
                            coreService.abort(bout);
                            continue;
                        }

                    }

                    String enStationId = entolllaneid.substring(0, 14);
                    //名称为空的场合添加名称
                    if (bout.getEntollstationname() == null || bout.getEntollstationname().length() == 1) {
                        String stationName = dataQueryService.queryStationName(bout.getEntolllanehex().substring(0, 8));
                        if (stationName == null) {
                            stationName = "未知收费站";
                        }
                        bout.setEntollstationname(stationName);
                    }


                    String exStationId = bout.getExtolllaneid().substring(0, 14);
                    List<Pallroutecomb> pallroutecombs = dataQueryService.queryPallroutecombList(enStationId, exStationId); // 费率列表

//                    Set<Integer> provinceIds = pallroutecombs.stream().map(Pallroutecomb::getTollprovinceid).collect(Collectors.toSet());
//                    if (provinceIds.size() != pallroutecombs.size()) {
//                        log.warn("=> duplicate provinceId, listno: {}", bout.getListno());
//                        continue;
//                    }

                    List<Boutlistdetail> newDetails = pallroutecombs.stream().map(r -> from(bout, r)).collect(Collectors.toList());


                    // 对于旧的明细数据，如果存在费率范围外的数据,则跳过处理
//                    Triple<List<Boutlistdetail>, List<Boutlistdetail>, List<Boutlistdetail>> diff = detailService.compare(oldDetails, newDetails);
//                    if (diff.getLeft().size() > 0) {
//                        log.warn("old detail not contain in pallroutecombs:{} ", bout.getListno());
//                        continue;
//                    }

//                    boolean deleteOldDetail = false;
//                    // 对于新旧中都有的值，删掉所有旧的明细数据
//                    if (diff.getRight().size() > 0) {
//                        log.debug("=> same exists, listno: {}, count:{}", bout.getListno(), diff.getRight().size());
//                        deleteOldDetail = true;
//                    }

                    if (newDetails.size() == 0) {
                        log.warn("No details found:{} ", bout.getListno());
                        coreService.abort(bout);
                    }

                    if (newDetails.size() > 0) {
                        log.debug("Insert new details:{} ", newDetails.size());

                        // 插入之前去掉角和分
                        // 根据费率中的对应金额算出总金额
                        Long pallTotal = newDetails.stream().mapToLong(Boutlistdetail::getTollfee).sum();
                        long cent = pallTotal % 100;
                        long fixVal;
                        if (cent >= 50) {
                            fixVal = 100 - cent;
                        } else {
                            fixVal = cent * -1;
                        }
                        for (Boutlistdetail detail : newDetails) {
                            if (detail.getProvinceid().startsWith("14")) {
                                updateDetail(detail, fixVal);
                                break;
                            }
                        }


                        coreService.doFix(bout, pallTotal + fixVal, entolllaneid, entolllanehex, exTolllandid, vehplate, invehplate, vehplateAuto, cardNo, passId, newDetails);
                    }

                } catch (Throwable e) {
                    log.error("error:, listno:" + bout.getListno(), e);
                }


            }


        }

    }


    private Pair<String, String> fixCardnoAndPassId(String cardno, String cardid, String passid) {
        if (passid == null || cardid == null || cardno == null) {
            return Pair.of(cardno, passid);
        }

        if (isETC()) {
            if (passid.length() > 30) {
                passid = cardno + passid.substring(passid.length() - 14, passid.length());
            }
            if (passid.length() > 30) {
                passid = null;
            }
            return Pair.of(cardno, passid);
        }


        if (!StringUtils.isEmpty(cardno) && !StringUtils.isEmpty(cardid) && !StringUtils.isEmpty(passid)) {
            if (cardno.length() >= 5 && cardno.length() < 16) {
                cardno = cardid;
                int length = passid.length();
                if (length > 30) {
                    passid = passid.substring(0, 30);
                    length = 30;
                }
                passid = cardid + passid.substring(length - 14, passid.length());
            } else {
                if (passid.length() > 30) {
                    passid = passid.substring(0, 30);
                }
            }
        }
        return Pair.of(cardno, passid);
    }


    private void updateDetail(Boutlistdetail detail, long fixVal) {
        if (fixVal == 0) {
            return;
        }
        String[] oldArray = detail.getChargefeegroup().split("\\|", -1);
        String[] newArray = new String[oldArray.length];
//        for (int i = 0; i < oldArray.length; i++) {
//            if (i == oldArray.length - 1) {
//                int num = Integer.valueOf(oldArray[i]);
//                newArray[i] = String.valueOf(num + fixVal);
//            } else {
//                newArray[i] = oldArray[i];
//            }
//
//        }

        boolean setFix = false;
        for (int i = oldArray.length - 1; i >= 0; i--) {
            boolean setIdx = false;
            int num = Integer.valueOf(oldArray[i]);
            if (fixVal > 0 || (num + fixVal) > 0) {
                if (!setFix) {
                    newArray[i] = String.valueOf(num + fixVal);
                    setFix = true;
                    setIdx = true;
                }
            }
            if (!setIdx) {
                newArray[i] = oldArray[i];
            }

        }


        detail.setTollfee(detail.getTollfee() + fixVal);
        detail.setChargefeegroup(String.join("|", newArray));
        detail.setChargepaygroup(detail.getChargefeegroup());

    }

/*
    public List<Boutlist> queryBoutList(int squaddate, int skip, int limit) {

        final String sql = "select t.* from ( select t1.ListNo,t1.VehType, t1.PTotalToll, t1.TotalToll, t1.enTollLaneId,t1.enTollLaneHex, " +
                "t1.exTollLaneId, t1.tollSupport, t1.stationno, t1.squaddate, rownum rowno from " + config.getBoutlist() + " t1 where squaddate=? " +
                "and instationno not in (select stdstationno from pstation) and vehclass=0 and totaltoll<>0 and rownum <= ? ) t where t.rowno > ?";

        return jdbcTemplate.query(sql, new Object[]{squaddate, skip + limit, skip}, new BeanPropertyRowMapper<>(Boutlist.class));
    }
*/

    public int getBoutlistTotal(int squaddate) {
        if (true){
            return 0;
        }
        int datatype = 1;
        if (!isETC()) {
            datatype = 6;
        }
        String sql;
        if (isETC()) {
            sql = "SELECT count(*) FROM " + config.getBoutlist() +
                    " WHERE squaddate=? and vehclass in(0,1) and totaltoll<>0 and ctranspackname not in (select packname from clear_pack_mulmtc_main where tablename = '" + config.getBoutlist() + "' and datatype = ? and upstatus = 1)";
        } else {
            sql = "SELECT count(*) FROM " + config.getBoutlist() +
                    " WHERE squaddate=? AND instationno not in (select stdstationno from pstation) and vehclass in(0,1) and totaltoll<>0 and ctranspackname not in (select packname from clear_pack_mulmtc_main where tablename = '" + config.getBoutlist() + "' and datatype = ? and upstatus = 1)";
        }


        return jdbcTemplate.queryForObject(sql, new Object[]{squaddate, datatype}, Integer.class);
    }




    public List<Boutlist> queryBoutList(int squaddate, String offsetNo, int limit) {

        if (false) {
            String sql = "select * FROM " + config.getBoutlist() + " where listno = ?";
            return jdbcTemplate.query(sql, new Object[]{"G000514039006020200502020011318000033"}, new BeanPropertyRowMapper<>(Boutlist.class));
        }


        int datatype = 1;
        String sql;
        if (!isETC()) {
            datatype = 6;
            sql = "SELECT * FROM (" +
                    "SELECT * FROM " + config.getBoutlist() +
                    " WHERE listno > ? AND ctranspackname <> '999' AND squaddate=? AND instationno not in (select stdstationno from pstation) and vehclass in(0,1) and totaltoll<>0 and ctranspackname not in (select packname from clear_pack_mulmtc_main where tablename = '" + config.getBoutlist() + "' and datatype = ? and upstatus = 1) ORDER BY listno ASC" +
                    ") WHERE rownum <=?";

        } else {

            sql = "SELECT * FROM (" +
                    "SELECT * FROM " + config.getBoutlist() +
                    " WHERE listno > ? AND ctranspackname <> '999' AND squaddate=?  and vehclass in(0,1) and totaltoll<>0 and ctranspackname not in (select packname from clear_pack_mulmtc_main where tablename = '" + config.getBoutlist() + "' and datatype = ? and upstatus = 1) ORDER BY listno ASC" +
                    ") WHERE rownum <=?";

        }


        return jdbcTemplate.query(sql, new Object[]{offsetNo, squaddate, datatype, limit}, new BeanPropertyRowMapper<>(Boutlist.class));
    }


//
//    public List<Boutlist> queryBoutList(int squaddate, String offsetNo, int limit) {
//        final String sql = "SELECT * FROM (" +
//                "SELECT ListNo, VehType, PTotalToll,TotalToll,enTollLaneId,enTollLaneHex,exTollLaneId,tollSupport,stationno,squaddate, cardId, cardNo, passId" +
//                " FROM " + config.getBoutlist() +
//                " WHERE listno > ? AND squaddate=? AND instationno not in (select stdstationno from pstation) and vehclass=0 and totaltoll<>0 ORDER BY listno ASC" +
//                ") WHERE rownum <=?";
//
//        return jdbcTemplate.query(sql, new Object[]{offsetNo, squaddate, limit}, new BeanPropertyRowMapper<>(Boutlist.class));
//    }


    private List<Boutlistdetail> queryBoutDetailList(String listNo) {
        return jdbcTemplate.query("SELECT * FROM " + config.getBoutlistDetail() + " WHERE LISTNO = ?",
                new Object[]{listNo}, new BeanPropertyRowMapper<>(Boutlistdetail.class));
    }



    private Boutlistdetail from(Boutlist bout, Pallroutecomb pallroutecomb) {
        Boutlistdetail detail = new Boutlistdetail();
        detail.setListno(bout.getListno());
        detail.setStationno(bout.getStationno());
        detail.setSquaddate(bout.getSquaddate());
        detail.setReceivetime(bout.getReceivetime());

        String provinceId = pallroutecomb.getTollprovinceid() == null ? null : pallroutecomb.getTollprovinceid().toString();
        if (provinceId != null && provinceId.length() == 2) {
            provinceId += "0201";
        }
        detail.setProvinceid(provinceId); //出还是进?
        detail.setTollsupport(4L);


        detail.setTollintervalscount(pallroutecomb.getTollintervalscount());
        detail.setTollintervalsgroup(pallroutecomb.getTollintervalsgroup());

        String transtime = "1970-01-01T00:00:00";
        String chargediscount = "0";
        StringBuilder sbTranstime = new StringBuilder();
        StringBuilder sbChargediscount = new StringBuilder();
        for (int i = 0; i < pallroutecomb.getTollintervalscount(); i++) {
            sbTranstime.append("|").append(transtime);
            sbChargediscount.append("|").append(chargediscount);
        }
        detail.setTranstimegroup(sbTranstime.substring(1));
        detail.setChargediscountgroup(sbChargediscount.substring(1));
//        detail.setChargepaygroup(pallroutecomb.getTollintervalsgroup());
//        detail.setRateversiongroup(pallroutecomb.getParamversion());
//        detail.setSectiongroup(StringUtils.isEmpty(pallroutecomb.getTollintervalsgroup()) ? null : pallroutecomb.getTollintervalsgroup().substring(0, 11));

        String sectiongroup = "";
        if (!StringUtils.isEmpty(pallroutecomb.getTollintervalsgroup())) {
            List<String> list = Arrays.asList(pallroutecomb.getTollintervalsgroup().split("\\|"));
            List<String> resultList = list.stream().map(each -> each.substring(0, 11)).collect(Collectors.toList());
            sectiongroup = String.join("|", resultList);
        }
        detail.setSectiongroup(sectiongroup);
        // 1-4 K1-K4,11-16 H1-H6,21-26 H11-H16

        switch (bout.getVehtype()) {
            case 1:
                detail.setTollfee(pallroutecomb.getTollfeek1());
                detail.setChargefeegroup(pallroutecomb.getChargefeegroupk1());
                break;

            case 2:
                detail.setTollfee(pallroutecomb.getTollfeek2());
                detail.setChargefeegroup(pallroutecomb.getChargefeegroupk2());
                break;
            case 3:
                detail.setTollfee(pallroutecomb.getTollfeek3());
                detail.setChargefeegroup(pallroutecomb.getChargefeegroupk3());
                break;
            case 4:
                detail.setTollfee(pallroutecomb.getTollfeek4());
                detail.setChargefeegroup(pallroutecomb.getChargefeegroupk4());
                break;
            case 11:
                detail.setTollfee(pallroutecomb.getTollfeeh1());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouph1());
                break;
            case 12:
                detail.setTollfee(pallroutecomb.getTollfeeh2());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouph2());
                break;
            case 13:
                detail.setTollfee(pallroutecomb.getTollfeeh3());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouph3());
                break;
            case 14:
                detail.setTollfee(pallroutecomb.getTollfeeh4());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouph4());
                break;
            case 15:
                detail.setTollfee(pallroutecomb.getTollfeeh5());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouph5());
            case 16:
                detail.setTollfee(pallroutecomb.getTollfeeh6());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouph6());
                break;
            case 21:
                detail.setTollfee(pallroutecomb.getTollfeehl1());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouphl1());
                break;
            case 22:
                detail.setTollfee(pallroutecomb.getTollfeehl2());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouphl2());
                break;
            case 23:
                detail.setTollfee(pallroutecomb.getTollfeehl3());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouphl3());
                break;
            case 24:
                detail.setTollfee(pallroutecomb.getTollfeehl4());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouphl4());
                break;
            case 25:
                detail.setTollfee(pallroutecomb.getTollfeehl5());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouphl5());
                break;
            case 26:
                detail.setTollfee(pallroutecomb.getTollfeehl6());
                detail.setChargefeegroup(pallroutecomb.getChargefeegrouphl6());
        }
        detail.setChargepaygroup(detail.getChargefeegroup());
//        Pair<Long, String> groupPair = computeFee(detail.getTollfee(), detail.getChargefeegroup());
//        detail.setTollfee(groupPair.getFirst());
//        detail.setChargefeegroup(groupPair.getSecond());

//        detail.setCreceivetime(new Date(System.currentTimeMillis()));//TOOD debug

        return detail;
    }


    private LocalDate parseDateString(String str) {
        if (str == null || str.length() < 8) {
            return null;
        }
        try {
            return LocalDate.parse(str, formatter);
        } catch (Throwable e) {
            log.error("parse date string error:", e);
            return null;
        }
    }


    public static Pair<Long, String> computeFee(Long fee, String group) {
        if (fee == null || StringUtils.isEmpty(group)) {
            return Pair.of(fee, group);
        }

        long cent = fee % 100;
        long fixVal;
        if (cent >= 50) {
            fixVal = 100 - cent;
        } else {
            fixVal = cent * -1;
        }
        String[] oldArray = group.split("\\|", -1);
        String[] newArray = new String[oldArray.length];
        for (int i = 0; i < oldArray.length; i++) {
            if (i == oldArray.length - 1) {
                int num = Integer.valueOf(oldArray[i]);
                newArray[i] = String.valueOf(num + fixVal);
            } else {
                newArray[i] = oldArray[i];
            }

        }
        return Pair.of(fee + fixVal, String.join("|", newArray));

    }

    private static java.sql.Date parseOpTime(String listno) {
        String dateStr = listno.substring(21, 21 + 14);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            Date date = simpleDateFormat.parse(dateStr);
            return new java.sql.Date(date.getTime());
        } catch (ParseException e) {
            log.error("parse optime error, listno：" + listno, e);
            return null;
        }
    }


}
